#ifndef _MGGS_INTERPCONDITONS_
#define _MGGS_INTERPCONDITONS_

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <cstdlib>
using namespace std;


template<class T, int Num> class InterpConditions;
 
template<class T, int Num> ostream & operator<<(ostream & os ,const InterpConditions<T,Num> &IC);

template <class T, int Num>
class InterpConditions{
 private:
  vector<vector<T> > Table_;
  vector<vector<bool> > BoolTable_;
 public:
  InterpConditions();
  InterpConditions(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab);
  InterpConditions(const string &_file);
  ~InterpConditions();
  void setTable(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab);
  void setTableByFile(const string &_file);
  const vector<vector<T> >& getTable() const;
  const vector<vector<bool> >& getBoolTable() const;
  friend ostream& operator<< <> (ostream& os, const InterpConditions<T,Num>& IC);
};



template <class T, int Num>
InterpConditions<T,Num>::InterpConditions(){};
    
template <class T, int Num>
InterpConditions<T,Num>::InterpConditions(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab){
  this->setTable(tab,booltab);
}

template <class T, int Num>
InterpConditions<T,Num>::InterpConditions(const string &_file){
  this->setTableByFile(_file);
}
  
template <class T, int Num>
InterpConditions<T,Num>::~InterpConditions(){};

template <class T, int Num>
void InterpConditions<T,Num>::setTable(const vector<vector<T> >& tab, const vector<vector<bool> >& booltab){
   if (tab.size() != Num+1 || booltab.size() != Num+1)
    cout << "Error! Size of table do not match." << endl;
  else{
    Table_ = tab;
    BoolTable_ = booltab;
  }
}

template <class T, int Num>
void InterpConditions<T,Num>::setTableByFile(const string &_file){
    std::fstream data(_file);
    int x,y;
    data >> x >> y;
    if (x != Num+1 || y < 1){
      cout << "Error! Size of table do not match." << endl;
      data.close();
    }
    else{
      vector<vector<T> > tab;
      vector<T> Tvec(y,0);
      vector<vector<bool> > booltab;
      vector<bool> boolvec(y,1);
      for (int i = 0 ; i < x ; i++){
        Tvec.clear();
        Tvec.resize(y,0);
        boolvec.clear();
        boolvec.resize(y,1);
        for (int j = 0 ; j < y ; j++){
           char c[20];
           data >> c;
           if (c[0] == '&')
             boolvec[j] = 0;
           else
             Tvec[j] = atof(c);
        }
        tab.push_back(Tvec);
        booltab.push_back(boolvec);
      }
      data.close();
      this -> setTable(tab,booltab);
    }
}



template <class T, int Num>
const vector<vector<T> >& InterpConditions<T,Num>::getTable() const{
  return Table_;
}
    
    
template <class T, int Num>
const vector<vector<bool> >& InterpConditions<T,Num>::getBoolTable() const{
  return BoolTable_;
}

template <class T, int Num>
ostream& operator<<(ostream& os, const InterpConditions<T,Num>& IC){
  vector<vector<T> > Ttab = IC.getTable();
  vector<vector<bool> > booltab = IC.getBoolTable();
  const int x = Ttab.size();
  const int y = Ttab[0].size();
  os << x << " " << y << endl;
  for (int i = 0 ; i < x ; i++){
    for (int j = 0 ; j < y ; j++){
      if (booltab[i][j] == 1)
        os << Ttab[i][j] << " ";
      else
        os << "& ";
    }
    os << "\b" << endl;
  }
  return os;  
}





#else
//do nothing
#endif
